<template>
  <div>
    <el-steps :active="active" align-center finish-status="success">
      <el-step title="基本配置"></el-step>
      <el-step title="接口配置"></el-step>
      <el-step title="参数类型配置"></el-step>
      <el-step title="参数映射配置"></el-step>
    </el-steps>
    <div class="configFormBox">
      <div style="width: 780px; margin: auto">
        <el-form
          ref="apiConfigForm"
          :inline="false"
          :model="apiConfigForm"
          label-position="right"
          label-width="100px"
          size="small"
          :rules="apiConfigFormRules"
        >
          <div
            class="basicFormBox"
            style="width: 450px; margin: auto"
            v-if="active === 0"
          >
            <el-alert
              title="Tips: http接口无需配置参数类型"
              type="info"
              show-icon
            ></el-alert
            ><br />
            <el-form-item label="协议类型" prop="protocol">
              <el-select
                :disabled="mode == 'UPDATE'"
                v-model="apiConfigForm.protocol"
                filterable
                placeholder="请选择"
                style="width: 100%"
              >
                <el-option
                  v-for="item in protocolOptions"
                  :key="item.value"
                  :label="item.label"
                  :value="item.value"
                >
                </el-option>
              </el-select>
            </el-form-item>
            <el-form-item label="API名称" prop="apiName">
              <el-input v-model="apiConfigForm.apiName"></el-input>
            </el-form-item>
            <el-form-item label="API路径" prop="path">
              <el-input
                v-model="apiConfigForm.path"
                placeholder="如：/hcc/test"
              ></el-input>
            </el-form-item>
            <el-form-item label="请求方法" prop="httpMethod">
              <el-select
                v-model="apiConfigForm.httpMethod"
                filterable
                placeholder="请选择"
                style="width: 100%"
              >
                <el-option
                  v-for="item in httpMethodOptions"
                  :key="item.value"
                  :label="item.label"
                  :value="item.value"
                >
                </el-option>
              </el-select>
            </el-form-item>
            <el-form-item
              label="MIME"
              prop="contentType"
              v-if="apiConfigForm.httpMethod === 'POST' || apiConfigForm.httpMethod === 'PUT'"
            >
              <el-select
                v-model="apiConfigForm.contentType"
                filterable
                placeholder="请选择"
                style="width: 100%"
              >
                <el-option
                  v-for="item in contentTypeOptions"
                  :key="item.value"
                  :label="item.label"
                  :value="item.value"
                >
                </el-option>
              </el-select>
            </el-form-item>
            <el-form-item label="API描述">
              <el-input
                type="textarea"
                v-model="apiConfigForm.apiDesc"
              ></el-input>
            </el-form-item>
            <el-form-item label="限流配置" prop="limit">
              <el-input v-model.number="apiConfigForm.limit">
                <template slot="append">/分钟</template>
              </el-input>
            </el-form-item>
            <div style="text-align: right; margin-top: 10px">
              <el-button type="primary" @click="clickNext" size="small"
                >下一步</el-button
              >
            </div>
          </div>
          <div
            class="interfaceFormBox"
            style="width: 450px; margin: auto"
            v-if="active === 1"
          >
            <div class="dubboFormBox" v-if="apiConfigForm.protocol === 'DUBBO'">
              <el-alert title="dubbo接口配置" type="info" show-icon></el-alert
              ><br />
              <el-form-item label="注册中心" prop="regCenterUrl">
                <el-input
                  type="textarea"
                  v-model="apiConfigForm.regCenterUrl"
                ></el-input>
              </el-form-item>
              <el-form-item label="接口名称" prop="interfaceName">
                <el-input v-model="apiConfigForm.interfaceName"></el-input>
              </el-form-item>
              <el-form-item label="方法名称" prop="methodName">
                <el-input v-model="apiConfigForm.methodName"></el-input>
              </el-form-item>
              <el-form-item label="版本号">
                <el-input v-model="apiConfigForm.version"></el-input>
              </el-form-item>
              <el-form-item label="超时时间">
                <el-input v-model="apiConfigForm.timeout"></el-input>
              </el-form-item>
              <el-form-item label="重试次数" prop="retryCount">
                <el-input v-model.number="apiConfigForm.retryCount"></el-input>
              </el-form-item>
              <el-form-item label="组">
                <el-input v-model="apiConfigForm.group"></el-input>
              </el-form-item>
            </div>
            <div class="httpFormBox" v-if="apiConfigForm.protocol === 'HTTP'">
              <el-alert title="http接口配置" type="info" show-icon></el-alert
              ><br />
              <el-form-item label="http地址" prop="targetUrl">
                <el-input v-model="apiConfigForm.targetUrl"></el-input>
              </el-form-item>
              <el-form-item label="重试次数" prop="retryCount">
                <el-input v-model.number="apiConfigForm.retryCount"></el-input>
              </el-form-item>
            </div>
            <div style="text-align: right; margin-top: 10px">
              <el-button @click="stepBefore" size="small">上一步</el-button>
              <el-button type="primary" @click="clickNext" size="small"
                >下一步</el-button
              >
            </div>
          </div>
          <div class="paramFormBox" v-if="active === 2" style="margin: auto; width: 680px">
            <div class="dubboParamFormBox">
              <el-alert
                title="dubbo泛化调用必须传入参数类型"
                type="warning"
                show-icon
              ></el-alert
              >
              <table
                class="paramFormTab"
                style="text-align: left; margin-top: 20px"
                cellspacing="0"
                cellpadding="0"
              >
                <th style="width: 150px; height: 30px">参数名</th>
                <th style="width: 300px">参数类型</th>
                <th style="width: 80px">自定义</th>
                <th style="width: 120px">
                  <el-button
                    v-if="apiConfigForm.paramTypeConfigs.length === 0"
                    size="mini"
                    icon="el-icon-plus"
                    type="primary"
                    circle
                    @click="addLine"
                  ></el-button>
                </th>
                <tbody>
                  <tr
                    v-for="(item, index) in apiConfigForm.paramTypeConfigs"
                    :key="index"
                  >
                    <td>
                      <el-form-item
                        :prop="'paramTypeConfigs.' + index + '.name'"
                        label-width="0"
                        :rules="[{ required: true, message: '参数名必填' }]"
                      >
                        <el-input
                          v-model="item.name"
                          size="small"
                          placeholder="请输入参数名称"
                        ></el-input>
                      </el-form-item>
                    </td>
                    <td>
                      <el-form-item
                        :prop="'paramTypeConfigs.' + index + '.type'"
                        label-width="0"
                        :rules="[{ required: true, message: '参数类型必填' }]"
                      >
                        <el-input
                          v-if="item.customer"
                          v-model="item.type"
                          size="small"
                          placeholder="请输入自定义参数类型"
                        ></el-input>
                        <el-select
                          v-if="!item.customer"
                          size="small"
                          v-model="item.type"
                          filterable
                          placeholder="请选择参数类型"
                          style="width: 100%"
                          clearable
                        >
                          <el-option
                            v-for="it in javaTypeOptions"
                            :key="it"
                            :label="it"
                            :value="it"
                          >
                          </el-option>
                        </el-select>
                      </el-form-item>
                    </td>
                    <td>
                      <el-form-item label-width="0">
                        <el-switch
                          size = 'mini'
                          v-model="item.customer"
                          @change="item.type = null"
                          active-color="#13ce66">
                        </el-switch>
                        <!-- <el-checkbox
                          v-model="item.customer"
                          @change="item.type = null"
                        ></el-checkbox> -->
                      </el-form-item>
                    </td>
                    <td>
                      <el-form-item label-width="0">
                        <el-button
                          v-if="
                            apiConfigForm.paramTypeConfigs.length === index + 1
                          "
                          type="primary"
                          size="mini"
                          icon="el-icon-plus"
                          circle
                          @click="addLine"
                        ></el-button>
                        <el-button
                          v-if="index >= 0"
                          size="mini"
                          icon="el-icon-minus"
                          type="danger"
                          circle
                          @click="removeLine(index)"
                        ></el-button>
                      </el-form-item>
                    </td>
                  </tr>
                </tbody>
              </table>
            </div>
            <div style="text-align: right; margin-top: 10px">
              <el-button @click="stepBefore" size="small">上一步</el-button>
              <el-button type="primary" @click="clickNext" size="small"
                >下一步</el-button
              >
            </div>
          </div>
          <div v-if="active === 3">
            <el-alert
              title="当未配置参数映射时，网关将会直接透传参数，DUBBO单个参数直接配置里面的字段，无需关心最外层"
              type="warning"
              show-icon
            ></el-alert>
            <!-- <el-form-item label="请求参数转换模板" label-width="150px">
              <el-input
                type="textarea"
                v-model="apiConfigForm.reqTemplate"
              ></el-input>
            </el-form-item>
            <el-form-item label="响应参数转换模板" label-width="150px">
              <el-input
                type="textarea"
                v-model="apiConfigForm.respTemplate"
              ></el-input>
            </el-form-item> -->
            <mapping-edit-table 
            v-model="apiConfigForm.reqParamMapping" 
            :rootName="reqRootName" 
            ref="reqEditTable"
            ></mapping-edit-table>
            <mapping-edit-table v-model="apiConfigForm.respParamMapping" :rootName="respRootName" ref="respEditTable"></mapping-edit-table>
            <div style="text-align: right; margin-top: 20px">
              <el-button @click="stepBefore" size="small">上一步</el-button>
              <el-button
                v-if="mode == 'CREATE'"
                type="primary"
                @click="submit"
                size="small"
                >提交</el-button
              >
              <el-button
                v-if="mode == 'UPDATE'"
                type="primary"
                @click="submit"
                size="small"
                >更新</el-button
              >
            </div>
          </div>
        </el-form>
      </div>
    </div>
  </div>
</template>
<script>
import ajax from "~/api/ajax";
import mappingEditTable from "~/components/mappingEditTable";

export default {
  props: {
    editApiConfigId: Number
  },
  watch: {
    editApiConfigId: {
      handler: function(newVal, oldVal) {
        const id = newVal;
        if (id == null) {
          return;
        }
        ajax.get("/apiManage/getFormApiConfig/" + id).then((rs) => {
          if (rs.success && rs.data != null) {
            this.apiConfigForm = rs.data;
            this.apiConfigForm.mode = 'UPDATE';
            this.mode = 'UPDATE';
          } else {
            this.$message.error(rs.msg + " 请尝试刷新！");
          }
        });
      },
      immediate: true
    }
  },
  inject: ['reload'],
  components: {
    "mapping-edit-table": mappingEditTable,
  },
  data() {
    return {
      mode: "CREATE",
      protocolOptions: [],
      javaTypeOptions: [
        "java.lang.Byte",
        "java.lang.Short",
        "java.lang.Integer",
        "java.lang.Float",
        "java.lang.Double",
        "java.lang.Long",
        "java.lang.Boolean",
        "java.lang.Character",
        "java.lang.String",
        "java.lang.BigDecimal",
        "java.util.List",
        "java.util.Map",
      ],
      contentTypeOptions: [
        {
          label: "application/json",
          value: "application/json",
        },
        {
          label: "application/x-www-form-urlencoded",
          value: "application/x-www-form-urlencoded",
        },
      ],
      httpMethodOptions: [
        {
          label: "GET",
          value: "GET",
        },
        {
          label: "POST",
          value: "POST",
        },
      ],
      active: 0,
      apiConfigForm: {
        mode: null,
        id: null,
        protocol: null,
        apiName: null,
        apiDesc: null,
        limit: 100,
        path: null,
        retryCount: 3,
        regCenterUrl: 'zookeeper://127.0.0.1:2181',
        interfaceName: null,
        methodName: null,
        group: null,
        timeout: null,
        targetUrl: null,
        paramTypeConfigs: [
          {
            name: null,
            type: null,
            customer: false,
          },
        ],
        reqTemplate: null,
        respTemplate: null,
        reqParamMapping: {
            pid: null,
            uid: "R",
            targetName: '请求参数配置',
            originalName: null,
            paramType: null,
            example: null,
            isRoot: false,
            required: false,
            children: [],
          },
        respParamMapping: {
            pid: null,
            uid: "R",
            targetName: '响应参数配置',
            originalName: null,
            paramType: null,
            example: null,
            isRoot: false,
            required: false,
            children: [],
          }
      },
      apiConfigFormRules: {
        protocol: [{ required: true, message: "必须选择协议类型" }],
        apiName: [{ required: true, message: "API名称不能为空" }],
        path: [
          { required: true, message: "API路径不能为空" },
          { pattern: /^(\/{1}\S+)+$/, message: "API路径非法" },
        ],
        limit: [
          { required: true, message: "限流配置不能为空" },
          { type: "number", message: "限流配置必须为数字" },
        ],
        regCenterUrl: [{ required: true, message: "注册中心不能为空" }],
        interfaceName: [{ required: true, message: "接口名称不能为空" }],
        methodName: [{ required: true, message: "方法名称不能为空" }],
        targetUrl: [{ required: true, message: "http地址不能为空" }],
        httpMethod: [{ required: true, message: "请求方法不能为空" }],
        contentType: [{ required: true, message: "Content-Type不能为空" }],
        retryCount: [
          { required: true, message: "重试次数不能为空" },
          { type: "number", message: "重试次数必须为数字" },
        ],
      },
      reqRootName: '请求参数配置',
      respRootName: '响应参数配置'
    };
  },
  mounted() {
    let that = this;
    ajax.get("/apiManage/protocols").then((rs) => {
      that.protocolOptions = rs.data;
    });
    ajax.get("/apiManage/httpMethods").then((rs) => {
      that.httpMethodOptions = rs.data;
    });
    let id = that.$route.query.id;
    if (id != undefined && id != null && id != "") {
      that.mode = "UPDATE";
      this.$message({
        message: "已进入编辑模式",
        type: "warning",
      });
      ajax.get("/apiManage/getFormApiConfig/" + id).then((rs) => {
        if (rs.success && rs.data != null) {
          that.apiConfigForm = rs.data;
        } else {
          this.$message.error(rs.msg + " 请尝试刷新！");
        }
      });
    }
  },
  methods: {
    stepBefore() {
      const that = this;
      if (that.apiConfigForm.protocol === "HTTP" && that.active === 3) {
        that.active = 1;
      } else {
        that.active--;
      }
    },
    clickNext() {
      const that = this;
      var fieldNameArr = [];
      if (that.active === 0) {
        fieldNameArr = ["apiName", "protocol", "path", "limit", "httpMethod"];
        if (that.apiConfigForm.httpMethod == "POST") {
            fieldNameArr.push("contentType");
          }
      } else if (that.active === 1) {
        if (that.apiConfigForm.protocol === "DUBBO") {
          fieldNameArr = [
            "regCenterUrl",
            "interfaceName",
            "methodName",
            "retryCount",
          ];
        } else if (that.apiConfigForm.protocol === "HTTP") {
          fieldNameArr = ["targetUrl", "retryCount"];
        }
      } else if (that.active === 2) {
        fieldNameArr = [];
        for (
          var index = 0;
          index < that.apiConfigForm.paramTypeConfigs.length;
          index++
        ) {
          fieldNameArr.push("paramTypeConfigs." + index + ".name");
          fieldNameArr.push("paramTypeConfigs." + index + ".type");
        }
      }
      Promise.all(
        fieldNameArr.map((item) => {
          return new Promise(function (resolve, reject) {
            that.$refs.apiConfigForm.validateField(item, (error) => {
              resolve(error);
            });
          });
        })
      ).then((data) => {
        console.info(data);
        // 去除数组空值
        data = data.filter((item) => item);
        if (!data.length) {
          if (that.active === 0) {
            ajax.post("/apiManage/validate", that.apiConfigForm).then((rs) => {
              if (!rs.success) {
                that.$message.error(rs.msg);
                return;
              }
              that.stepNext();
            });
          } else {
            that.stepNext();
          }
        }
      });
    },
    stepNext() {
      const that = this;
      if (that.apiConfigForm.protocol === "HTTP" && that.active === 1) {
        that.active = 3;
      } else {
        that.active++;
      }
    },
    validateFields(fieldNameArr, callback) {
      const that = this;
    },
    addLine() {
      const that = this;
      that.apiConfigForm.paramTypeConfigs.push({
        name: null,
        type: null,
        customer: false,
      });
    },
    removeLine(index) {
      const that = this;
      that.apiConfigForm.paramTypeConfigs.splice(index, 1);
    },
    submit() {
      let that = this;
      console.log(JSON.stringify(this.apiConfigForm));
      let tilte = that.mode == 'CREATE' ? '确定提交？' : '确定更新？';
      let msg = that.mode == 'CREATE' ? '保存成功！' : '更新成功！';
      this.$confirm(tilte, "提示", {
        confirmButtonText: "确定",
        cancelButtonText: "取消",
        type: "warning",
      }).then(() => {
        // 调用接口
        ajax.post("/apiManage/create", that.apiConfigForm).then((rs) => {
          if (rs.success) {
            this.$message({
              type: "success",
              message: msg,
            });
            
            if (that.mode == 'CREATE') {
              that.reload();
            } else {
              this.$emit("submitEdit");
            }
          }
        });
      });
    },
    appendChild(row) {
      const id = row.id + '_' + (row.children.length + 1);
      row.children.push({
        parentId: row.id,
        id: id,
        targetName: "" + id,
        originalName: "" + id,
        children: [],
      });
    },
    remove(row) {
      const parentId = row.parentId;
      const id = row.id;

      console.log('父id：' + parentId + ' id: ' + row.id);
      const tableData = this.findTableData(this.reqParamTabData, parentId);
      alert(JSON.stringify(tableData));

      const arr = tableData.children;
      for (var i = 0; i < arr.length; i++) {
        if (arr[i].id === id) {
          arr.splice(i, 1);
        }
      }
    },
    findTableData(tableData, id) {
      for (var i = 0; i < tableData.length; i++) {
        if (tableData[i].id === id) {
            return tableData[i];
        }

        return this.findTableData(tableData[i].children, id);
      }
    },
  },
};
</script>
<style>
.configFormBox {
  margin-top: 30px;
  height: 100%;
  width: 100%;
}
.paramFormTab th,
td {
  padding-right: 10px;
}
.el-tree > .el-tree-node {
  display: inline-block;
  min-width: 100%;
}
</style>